package controller

import (
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/mvc"
	"context"
	"fmt"
	"net/url"
	"io"
	"os"
	"time"
	"gowork/studentGoKit/client/transport"
	stuEndpoint "gowork/studentGoKit/client/endpoint"
	httpTransport "github.com/go-kit/kit/transport/http"
	"gowork/studentGoKit/client/util"
	"github.com/go-kit/kit/endpoint"
	"github.com/go-kit/kit/sd"
	"github.com/go-kit/kit/sd/lb"
	"github.com/go-kit/kit/log"

	"github.com/afex/hystrix-go/hystrix"
)

type StudentKitController struct{
    Ctx  iris.Context
}

var logger log.Logger = log.NewLogfmtLogger(os.Stdout)

func (c *StudentKitController) PostKitinsert() mvc.Result {
	id := c.Ctx.FormValue("id")
	name := c.Ctx.FormValue("name")
	birth := c.Ctx.FormValue("birth")
	sex := c.Ctx.FormValue("sex")

	// tgt, _ := url.Parse("http://127.0.0.1:7777")
	// insertClient := httpTransport.NewClient("GET", tgt, transport.StudentInsertRequest, transport.StudentMapResponse)
	// studentInsert := insertClient.Endpoint()

	// ctx := context.Background()
	// res, err := studentInsert(ctx, stuEndpoint.StudentRequest{Id: id, Name: name, Birth: birth, Sex: sex,})
	// if err != nil{
	// 	fmt.Println(err)
	// 	return mvc.Response{
	// 		Object : err,
	// 	}
	// }
	
	factory := func(serviceUrl string)(endpoint.Endpoint, io.Closer, error){
		tart, _ := url.Parse("http://" + serviceUrl)
		fmt.Println(serviceUrl)
		fmt.Println("tart:", tart)
		return httpTransport.NewClient("GET", tart, transport.StudentInsertRequest, transport.StudentMapResponse).Endpoint(), nil, nil
	}

	endpointer:= sd.NewEndpointer(util.Instancer, factory, logger)

	endpoints, eErr := endpointer.Endpoints()
	if eErr != nil{
		fmt.Println(eErr)
		return mvc.Response{
			Object : eErr,
		}
	}
	fmt.Println("服务端实例:", endpoints, len(endpoints))


	//负载均衡
	//myLb := lb.NewRoundRobin(endpointer)
	myLb := lb.NewRandom(endpointer, time.Now().UnixNano())
	
	studentInsertFunc, uErr := myLb.Endpoint()
	if uErr != nil{
		fmt.Println("获取方法报错", uErr)
		return mvc.Response{
			Object : uErr,
		}
	}
	ctx := context.Background()
	res, err := studentInsertFunc(ctx, stuEndpoint.StudentRequest{Id: id, Name: name, Birth: birth, Sex: sex,})
	if err != nil{
		fmt.Println("调用方法报错", err)
		return mvc.Response{
			Object : err,
		}
	}

	return mvc.Response{
        Object : res.(stuEndpoint.StudentMapResponse),
    }
}

func (c *StudentKitController) PostKitdelete() mvc.Result {
	name := c.Ctx.FormValue("name")

	// tgt, _ := url.Parse("http://127.0.0.1:7777")
	// deleteClient := httpTransport.NewClient("GET", tgt, transport.StudentDeleteRequest, transport.StudentMapResponse)
	// studentDelete := deleteClient.Endpoint()

	// ctx := context.Background()
	// res, err := studentDelete(ctx, stuEndpoint.StudentNameRequest{Name: name,})
	// if err != nil {
	// 	fmt.Println(err)
	// 	return mvc.Response{
	// 		Object : err,
	// 	} 
	// }

	factory := func(serviceUrl string)(endpoint.Endpoint, io.Closer, error){
		tart, _ := url.Parse("http://" + serviceUrl)
		return httpTransport.NewClient("GET", tart, transport.StudentDeleteRequest, transport.StudentMapResponse).Endpoint(), nil, nil
	}

	endpointer:= sd.NewEndpointer(util.Instancer, factory, logger)

	//负载均衡
	//myLb := lb.NewRoundRobin(endpointer)
	myLb := lb.NewRandom(endpointer, time.Now().UnixNano())
	
	studentDeleteFunc, uErr := myLb.Endpoint()
	if uErr != nil{
		fmt.Println(uErr)
		return mvc.Response{
			Object : uErr,
		}
	}
	ctx := context.Background()
	res, err := studentDeleteFunc(ctx, stuEndpoint.StudentNameRequest{Name: name,})
	if err != nil{
		fmt.Println(err)
		return mvc.Response{
			Object : err,
		}
	}

	return mvc.Response{
		Object : res.(stuEndpoint.StudentMapResponse),
	}
}

func (c *StudentKitController) PostKitupdate() mvc.Result {
	id := c.Ctx.FormValue("id")
	name := c.Ctx.FormValue("name")
	birth := c.Ctx.FormValue("birth")
	sex := c.Ctx.FormValue("sex")

	// tgt, _ := url.Parse("http://127.0.0.1:7777")
	// updateClient := httpTransport.NewClient("GET", tgt, transport.StudentUpdateRequest, transport.StudentMapResponse)
	// studentUpdate := updateClient.Endpoint()

	// ctx := context.Background()
	// res, err := studentUpdate(ctx, stuEndpoint.StudentRequest{Id: id, Name: name, Birth: birth, Sex: sex,})
	// if err != nil{
	// 	fmt.Println(err)
	// 	return mvc.Response{
	// 		Object : err,
	// 	}
	// }
	
	factory := func(serviceUrl string)(endpoint.Endpoint, io.Closer, error){
		tart, _ := url.Parse("http://" + serviceUrl)
		return httpTransport.NewClient("GET", tart, transport.StudentUpdateRequest, transport.StudentMapResponse).Endpoint(), nil, nil
	}

	endpointer:= sd.NewEndpointer(util.Instancer, factory, logger)
	//负载均衡
	//myLb := lb.NewRoundRobin(endpointer)
	myLb := lb.NewRandom(endpointer, time.Now().UnixNano())
	
	studentUpdateFunc, uErr := myLb.Endpoint()
	if uErr != nil{
		fmt.Println(uErr)
		return mvc.Response{
			Object : uErr,
		}
	}
	ctx := context.Background()
	res, err := studentUpdateFunc(ctx, stuEndpoint.StudentRequest{Id: id, Name: name, Birth: birth, Sex: sex,})
	if err != nil{
		fmt.Println(err)
		return mvc.Response{
			Object : err,
		}
	}

	return mvc.Response{
        Object : res.(stuEndpoint.StudentMapResponse),
    }
}

func (c *StudentKitController) PostKitquery() mvc.Result {

	// tgt, _ := url.Parse("http://127.0.0.1:7777")
	// queryClient := httpTransport.NewClient("GET", tgt, transport.StudentQueryRequest, transport.StudentQueryResponse)
	// studentQuery := queryClient.Endpoint()

	// ctx := context.Background()
	// res, err := studentQuery(ctx, stuEndpoint.StudentNilRequest{})
	// if err != nil{
	// 	fmt.Println(err)
	// 	return mvc.Response{
	// 		Object : err,
	// 	}
	// }
	
	factory := func(serviceUrl string)(endpoint.Endpoint, io.Closer, error){
		tart, _ := url.Parse("http://" + serviceUrl)
		return httpTransport.NewClient("GET", tart, transport.StudentQueryRequest, transport.StudentQueryResponse).Endpoint(), nil, nil
	}

	endpointer:= sd.NewEndpointer(util.Instancer, factory, logger)

	//负载均衡
	myLb := lb.NewRoundRobin(endpointer)
	//myLb := lb.NewRandom(endpointer, time.Now().UnixNano())
	
	studentQueryFunc, uErr := myLb.Endpoint()
	if uErr != nil{
		fmt.Println(uErr)
		return mvc.Response{
			Object : uErr,
		}
	}
	
	configHystrix := hystrix.CommandConfig{
		Timeout: 1000,
		MaxConcurrentRequests: 5,
		RequestVolumeThreshold: 3,
		ErrorPercentThreshold: 20,
		SleepWindow: int(time.Second*100),
	}
	hystrix.ConfigureCommand("studentQuery", configHystrix)
	var res interface{}
	var err error
	err = hystrix.Do("studentQuery", func() error{
		ctx := context.Background()
		res, err = studentQueryFunc(ctx, stuEndpoint.StudentNilRequest{})
		fmt.Println(res)
		return err
	}, func(e error) error{
		res = map[string]string{
			"code" : "500",
			"message" : "服务降级",
		}
		return nil
	})
	if err != nil{
		fmt.Println(err)
	}

	// ctx := context.Background()
	// res, err := studentQueryFunc(ctx, stuEndpoint.StudentNilRequest{})
	// if err != nil{
	// 	fmt.Println(err)
	// 	return mvc.Response{
	// 		Object : err,
	// 	}
	// }
	
	return mvc.Response{
        Object : res.(stuEndpoint.StudentResponse),
    }
}